package com.tumblr.anond2.solr.client.solrj;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer.RemoteSolrException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;

/**
 * Solr RDB-like client.O
 * <p>See TestSolrRDBClient code.</p>
 */
public class SolrRDBClient {

	final static Logger logger = LoggerFactory.getLogger(SolrRDBClient.class);
	
	private static SolrRDBClient instance = new SolrRDBClient();
	private static SolrServer server = null;
	
	private SolrRDBClient() {
	}
	
	public static SolrRDBClient getInstance() throws Exception {
		server = checkNotNull(SolrConnection.getSolrServer(), "server not found");
		return instance;
	}

	public QueryResponse getQueryResponse(ModifiableSolrParams params) throws Exception{
		QueryResponse response = server.query(params);
		return response;
	}

	public QueryResponse getQueryResponse(String query, Map<String, String> additionalParams) throws Exception{	
		ModifiableSolrParams params = new ModifiableSolrParams();
		checkNotNull(query, "query can't be null");
		params.add("q", query);	
		if (additionalParams != null){
			for (String key : additionalParams.keySet()){
				params.add(key, additionalParams.get(key));
			}
		}
		QueryResponse response = server.query(params);
		return response;
	}

	public SolrDocumentList get(String query, Map<String, String> additionalParams) throws Exception{	
		QueryResponse response = getQueryResponse(query, additionalParams);
		SolrDocumentList docs = (SolrDocumentList) response.getResults();
		return docs;
	}

	public static Table<String, String, Object> parseTable(SolrDocumentList docs){
		Table<String, String, Object> table = HashBasedTable.create();
		for (SolrDocument doc : docs){
			String key = doc.getFieldValue("id").toString();
			for (String field : doc.getFieldNames()){
				if (!field.equals("id")){
					Object value = doc.getFieldValue(field);
					table.put(key, field, value);
				}
			}
		}
		return table;
	}
	
	public boolean set(String id, List<String> fields, List<Object> values, Object version) throws Exception{
		SolrInputDocument doc = new SolrInputDocument();
		doc.addField("id", id);
		if (version != null) doc.addField("_version_", Long.parseLong(version.toString()));
		int i = 0;
		for (String field : fields){
			Map<String, Object> map = Maps.newHashMap();
			map.put("set", values.get(i));
			doc.addField(field, map);
			i++;
		}
		try{
			server.add(doc);
		} catch (RemoteSolrException e){
			//logger.error(e.getMessage(), e);
			return false;
		}
		server.commit(false, false, true);
		return true;
	}
	
	public boolean add(String id, List<String> fields, List<Object> values) throws Exception{
		SolrInputDocument doc = new SolrInputDocument();
		doc.addField("id", id);
		int i = 0;
		for (String field : fields){
			doc.addField(field, values.get(i));
			i++;
		}
		try{
			server.add(doc);
		} catch (RemoteSolrException e){
			//logger.error(e.getMessage(), e);
			return false;
		}
		server.commit(false, false, true);
		return true;
	}
	
	public boolean delete(List<String> ids) throws Exception{
		server.deleteById(ids);
		server.commit(false, false, true);
		return true;
	}
	
	public void delete(String query) throws Exception{
		server.deleteByQuery(query);
		server.commit(false, false, true);
	}
	
}
